package com.luxsoft.sw3.cfd.crypto;

import java.io.File;
import java.io.FileInputStream;
import java.security.AlgorithmParameters;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.EncryptedPrivateKeyInfo;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

import org.apache.commons.lang.ArrayUtils;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.util.ASN1Dump;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.core.io.FileSystemResource;

public class Cifrado {

	public static void readKey() throws Exception {
		FileSystemResource resource = new FileSystemResource(
				"C:\\pruebas\\cfd\\prueba3\\aaa010101aaa_CSD_01.key");
		File keyFile = resource.getFile();
		System.out.println("Encode key size: " + keyFile.length());
		FileInputStream keyfis = new FileInputStream(resource.getFile());
		byte[] encKey = new byte[keyfis.available()];
		keyfis.read(encKey);
		keyfis.close();

		java.security.Security.addProvider(new BouncyCastleProvider());

		String algName="PBEWitSHA1AndDES";
		PBEKeySpec pbeKeySpec = new PBEKeySpec("a0123456789".toCharArray());
		SecretKeyFactory skFac = SecretKeyFactory.getInstance(algName,"BC");
		
		Cipher cipher = Cipher.getInstance(algName, "BC");
		cipher.init(Cipher.WRAP_MODE, skFac.generateSecret(pbeKeySpec),cipher.getParameters());

		ASN1InputStream as1=new ASN1InputStream(encKey);
		//System.out.println(ASN1Dump.dumpAsString(as1.readObject()));
		EncryptedPrivateKeyInfo ePKInfo = new EncryptedPrivateKeyInfo(cipher.getParameters(),as1.readObject().getEncoded());
		System.out.println("Alg: "+ePKInfo.getAlgName());
		System.out.println("Alg params: "+ePKInfo.getAlgParameters());

		String pbeAlgorithm = "PBES2";

		
		
		cipher.init(Cipher.DECRYPT_MODE, skFac.generateSecret(pbeKeySpec),
				ePKInfo.getAlgParameters());
		PKCS8EncodedKeySpec pkcs8Spec = ePKInfo.getKeySpec(cipher);
		KeyFactory keyFact = KeyFactory.getInstance("RSA", "BC");
		/*
		 * RSAPrivateCrtKey privKey =
		 * (RSAPrivateCrtKey)keyFact.generatePrivate(pkcs8Spec);
		 * RSAPublicKeySpec rsaPubKeySpec = new
		 * RSAPublicKeySpec(privKey.getModulus(), privKey.getPublicExponent());
		 * RSAPublicKey rsaPubKey = (RSAPublicKey)
		 * keyFact.generatePublic(rsaPubKeySpec);
		 */

	}

	public static void readPrivateKey() throws Exception{
		
		java.security.Security.addProvider(new BouncyCastleProvider());
		
		//KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
		//kpg.initialize(128, Util.createFixedRandom());

		//KeyPair pair = kpg.generateKeyPair();
		FileSystemResource resource = new FileSystemResource("C:\\pruebas\\cfd\\prueba3\\aaa010101aaa_CSD_01.key");
		File keyFile = resource.getFile();
		System.out.println("Encode key size: " + keyFile.length());
		FileInputStream keyfis = new FileInputStream(resource.getFile());
		byte[] wrappedKey = new byte[keyfis.available()];
		keyfis.read(wrappedKey);
		keyfis.close();

		// wrapping step
		char[] password = "a0123456789".toCharArray();
		//byte[] salt = new byte[20];
		//int iCount = 100;
		//String pbeAlgorithm = "PBEWithSHAAnd3-KeyTripleDES-CBC";
		String pbeAlgorithm = "PBEWithMD5AndDES";
		
		//PBEKeySpec pbeKeySpec = new PBEKeySpec(password, salt, iCount);
		PBEKeySpec pbeKeySpec = new PBEKeySpec(password);
		SecretKeyFactory secretKeyFact = SecretKeyFactory.getInstance(
				pbeAlgorithm, "BC");
		Cipher cipher = Cipher.getInstance(pbeAlgorithm, "BC");

		cipher.init(Cipher.WRAP_MODE, secretKeyFact.generateSecret(pbeKeySpec));

		//byte[] wrappedKey = cipher.wrap(pair.getPrivate());

		// create carrier
		EncryptedPrivateKeyInfo pInfo = new EncryptedPrivateKeyInfo(cipher
				.getParameters(), wrappedKey);

		// unwrapping step - note we only use the password
		pbeKeySpec = new PBEKeySpec(password);

		cipher = Cipher.getInstance(pInfo.getAlgName(), "BC");

		cipher.init(Cipher.DECRYPT_MODE, secretKeyFact
				.generateSecret(pbeKeySpec), pInfo.getAlgParameters());

		PKCS8EncodedKeySpec pkcs8Spec = pInfo.getKeySpec(cipher);
		KeyFactory keyFact = KeyFactory.getInstance("RSA", "BC");
		PrivateKey privKey = keyFact.generatePrivate(pkcs8Spec);
		
		

	}
	
	public static void read()throws Exception{
		String cadenaOriginal="SISTEMA DE ENCRIPTAMIENTO SIIPAP WIN";
		java.security.Security.addProvider(new BouncyCastleProvider());
		FileSystemResource resource = new FileSystemResource("C:\\pruebas\\cfd\\pruebas4\\my_pk.key");
		File keyFile = resource.getFile();
		System.out.println("Encode key size: " + keyFile.length());
		FileInputStream keyfis = new FileInputStream(resource.getFile());
		byte[] wrappedKey = new byte[keyfis.available()];
		keyfis.read(wrappedKey);
		keyfis.close();
		
		PKCS8EncodedKeySpec pkcs8keySpec=new PKCS8EncodedKeySpec(wrappedKey);
		KeyFactory keyFactory=KeyFactory.getInstance("RSA","BC");
		PrivateKey privateKey=keyFactory.generatePrivate(pkcs8keySpec);
		
		Cipher cipher=Cipher.getInstance("RSA","BC");
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		byte[] encryptedData=cipher.doFinal(cadenaOriginal.getBytes("UTF-8"));
		byte[] base64EncryptedData=Base64.encode(encryptedData);
		System.out.println("Encrypted  data: "+ArrayUtils.toString(encryptedData));
		String selloDigital=new String(base64EncryptedData);
		System.out.println("Sello Digital: "+selloDigital);
		
		//Verificando 
		FileSystemResource publicKeyResource = new FileSystemResource("C:\\pruebas\\cfd\\pruebas4\\aaa010101aaa_CSD_06.cer");
		/*File publicFile = publicKeyResource.getFile();
		FileInputStream publicKeyIs = new FileInputStream(publicFile);
		byte[] encodedPublicKey = new byte[publicKeyIs.available()];
		publicKeyIs.read(encodedPublicKey);
		publicKeyIs.close();
		*/
		CertificateFactory fact = CertificateFactory.getInstance("X.509","BC");

	      // read the certificate
	    X509Certificate x509Cert = (X509Certificate)fact.generateCertificate(publicKeyResource.getInputStream());

	    System.out.println("issuer: " + x509Cert.getIssuerX500Principal());
	    cipher.init(Cipher.DECRYPT_MODE, x509Cert);
	    
	    byte[] base64Decrypted=Base64.decode(selloDigital.getBytes());
	    System.out.println("Decrypted Sello: "+ArrayUtils.toString(base64Decrypted));
	    byte[] decryptedData=cipher.doFinal(base64Decrypted);
	    System.out.println(" Decrypted data: "+ArrayUtils.toString(decryptedData));

		
	}
	
	public static void decript() throws Exception{
		java.security.Security.addProvider(new BouncyCastleProvider());
		String raw="Pc96s7U/ogehWbZsbUrlpdO0NOkjz4rbpolgzx7pMlQuLV6tqC8sCOPvyqQYdRxkp/gcZtoWH9wh4FQfPTIqmA0jOGkItmxVz7Z81mggfCcdxgEkTaAZGDE0RGt+UT74O1vvwbyYxXbc4gMpgyGMJxIfM3ymAc8dr6GqYqcFI7U=";
		byte[] decodedData=Base64.decode(raw);
		System.out.println("Encrypted base64: "+raw);
		System.out.println("Encripted raw   : "+ArrayUtils.toString(decodedData));
		FileSystemResource publicKeyResource = new FileSystemResource("C:\\pruebas\\cfd\\pruebas4\\aaa010101aaa_CSD_05.cer");
		CertificateFactory fact = CertificateFactory.getInstance("X.509","BC");

	      // read the certificate
	    X509Certificate certificate = (X509Certificate)fact.generateCertificate(publicKeyResource.getInputStream());
	    Cipher cipher=Cipher.getInstance("RSA","BC");
	    cipher.init(Cipher.DECRYPT_MODE, certificate);
	    byte[] decryptedData=cipher.doFinal(decodedData);
	    System.out.println("Data: "+new String(decryptedData,"UTF-8"));

	}

	public static void main(String[] args) {
		try {
			readKey();
			//read();
			//decript();
			} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
